package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	if len(os.Args) < 3 {
		log.Fatalln("必须跟上ip 和 端口")
	}
	addr := os.Args[1]
	port := os.Args[2]

	ipAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%v:%v", addr, port))
	if err != nil {
		log.Fatal(err)
	}

	listener, err := net.ListenTCP("tcp", ipAddr)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()
	log.Println("开始监听....")
	for {
		con, err := listener.Accept()
		log.Printf("接受到客户端... ip: %v", con.RemoteAddr())
		if err != nil {
			log.Print(err)
			continue
		}
		go handleCon(con)
	}

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	<-sigs
	os.Exit(0)
}

func handleCon(conn net.Conn) {
	defer func() {
		if v := recover(); v != nil {
			log.Println(v)
		}
	}()

	result := bytes.NewBuffer(nil)
	var buf [65542]byte
	for {
		n, err := conn.Read(buf[0:])
		log.Println("读到数据",string(buf[0:n]), err)
		result.Write(buf[0:n])
		if err != nil {
			if err == io.EOF {
				log.Print("连接断开")
				return
			} else {
				log.Println("handleCon for", err)
			}
		} else {
			scanner := bufio.NewScanner(result)
			scanner.Split(packetSlitFunc)
			for scanner.Scan() {
				r := scanner.Bytes()[6:]
				log.Print(string(r))
				callbackStr := fmt.Sprintf("服务端收到信息返回给客户端: %v", string(r))
				if _, err := conn.Write(sendPkg(callbackStr)); err != nil {
					log.Println("发送出错: ", err.Error())
				}
			}
		}
		result.Reset()
	}

}

func packetSlitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if !atEOF && len(data) > 6 && binary.BigEndian.Uint32(data[:4]) == 0x123456 {
		var l int16
		binary.Read(bytes.NewReader(data[4:6]), binary.BigEndian, &l)
		pl := int(l) + 6
		if pl <= len(data) {
			return pl, data[:pl], nil
		}
	}
	return
}

func sendPkg(msg string) []byte {
	bbys := []byte(msg)
	magicNum := make([]byte, 4)
	binary.BigEndian.PutUint32(magicNum, 0x123456)
	lenNum := make([]byte, 2)
	binary.BigEndian.PutUint16(lenNum, uint16(len(bbys)))
	packetBuf := bytes.NewBuffer(magicNum)
	packetBuf.Write(lenNum)
	packetBuf.Write(bbys)
	return packetBuf.Bytes()
}
